package com.lifengdi.qiankun.message;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.DingTalkSignatureUtil;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.lifengdi.qiankun.message.enums.DingTalkMessageTypeEnum;
import com.lifengdi.qiankun.message.properties.DingTalkRobotProperties;
import com.lifengdi.qiankun.message.request.DingTalkRobotRequest;
import com.lifengdi.qiankun.message.request.IRequest;
import com.taobao.api.ApiException;
import com.taobao.api.internal.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * 钉钉群机器人消息
 *
 * @author: 李锋镝
 * @date: 2020-08-20 18:39
 */
public class DingTalkRobotMessageHandler extends AbstractMessageHandler {

    private static Logger logger = LoggerFactory.getLogger(DingTalkRobotMessageHandler.class);

    @Resource
    private DingTalkRobotProperties dingTalkRobotProperties;

    private static boolean checkSuccessful = false;

    @Override
    public void execute(IRequest request) throws ApiException {
        if (Objects.isNull(request)) {
            return;
        }

        // 配置校验
        checkConfig();

        DingTalkRobotRequest dingTalkRobotRequest = (DingTalkRobotRequest) request;
        String robotUrl = dingTalkRobotProperties.getRobotUrl();

        if (StringUtils.isEmpty(dingTalkRobotRequest.getMsgtype())) {
            dingTalkRobotRequest.setMsgtype(dingTalkRobotProperties.getMessageType());
        }

        cn.kuaidao.message.enums.DingTalkSecurityTypeEnum securityEnum = cn.kuaidao.message.enums.DingTalkSecurityTypeEnum.getByType(dingTalkRobotProperties.getSecurity().getType());
        if (cn.kuaidao.message.enums.DingTalkSecurityTypeEnum.KEYWORD.equals(securityEnum)) {
            checkKeyword(dingTalkRobotRequest);
        }
        if (cn.kuaidao.message.enums.DingTalkSecurityTypeEnum.SIGN.equals(securityEnum)) {
            robotUrl = sign();
        }

        // 发送消息
        DingTalkClient client = new DefaultDingTalkClient(robotUrl);
        OapiRobotSendResponse response = client.execute(dingTalkRobotRequest);

        if (logger.isDebugEnabled()) {
            logger.debug(response.getBody());
        }
    }

    /**
     * 签名并返回签名后的url
     *
     * @return 签名后的url
     */
    private String sign() {
        Long timestamp = System.currentTimeMillis();
        String secret = dingTalkRobotProperties.getSecurity().getSignSecret();
        // 验证签名有效性
        String canonicalString = DingTalkSignatureUtil.getCanonicalStringForIsv(timestamp, secret);
        String signature = DingTalkSignatureUtil.computeSignature(secret, canonicalString);
        String robotUrl = dingTalkRobotProperties.getRobotUrl();
        String queryStr = "timestamp=" + timestamp + "&sign=" + signature;
        if (robotUrl.indexOf("?") > 0) {
            robotUrl = robotUrl + "&" + queryStr;
        } else {
            robotUrl = robotUrl + "?" + queryStr;
        }
        return robotUrl;
    }

    /**
     * 校验关键字
     *
     * @param request DingTalkRobotRequest
     */
    private void checkKeyword(DingTalkRobotRequest request) {
        String securityType = dingTalkRobotProperties.getSecurity().getType();
        if (cn.kuaidao.message.enums.DingTalkSecurityTypeEnum.KEYWORD.getSecurityType().equalsIgnoreCase(securityType)) {
            DingTalkMessageTypeEnum messageTypeEnum = DingTalkMessageTypeEnum.getByType(request.getMsgtype());
            String keyword = dingTalkRobotProperties.getSecurity().getKeyword();
            String content = null;
            switch (Objects.requireNonNull(messageTypeEnum)) {
                case TEXT:
                    content = request.getText();
                    break;
                case LINK:
                    content = request.getLink();
                    break;
                case MARKDOWN:
                    content = request.getMarkdown();
                    break;
                case ACTION_CARD:
                    content = request.getActionCard();
                    break;
                case FEED_CARD:
                    content = request.getFeedCard();
                    break;
            }

            Objects.requireNonNull(content, "message content can't be empty");
            if (!content.contains(keyword)) {
                throw new IllegalArgumentException("Illegal message content:" + content + ", content missing keywords:" + keyword);
            }
        }
    }

    /**
     * 配置参数校验
     */
    private void checkConfig() {
        if (checkSuccessful) {
            return;
        }
        String robotUrl = dingTalkRobotProperties.getRobotUrl();
        if (StringUtils.isEmpty(robotUrl)) {
            throw new NullPointerException("robotUrl can't be empty");
        } else if (!robotUrl.startsWith("http")) {
            throw new IllegalArgumentException("Illegal robotUrl:" + robotUrl);
        }

        String securityType = dingTalkRobotProperties.getSecurity().getType();
        if (StringUtils.isEmpty(securityType)) {
            throw new NullPointerException("securityType can't be empty");
        } else {
            cn.kuaidao.message.enums.DingTalkSecurityTypeEnum securityTypeEnum = cn.kuaidao.message.enums.DingTalkSecurityTypeEnum.getByType(securityType);
            switch (securityTypeEnum) {
                case KEYWORD:
                    if (StringUtils.isEmpty(dingTalkRobotProperties.getSecurity().getKeyword())) {
                        throw new NullPointerException("keyword can't be empty");
                    }
                    break;
                case SIGN:
                    String secret = dingTalkRobotProperties.getSecurity().getSignSecret();
                    if (StringUtils.isEmpty(secret)) {
                        throw new NullPointerException("secret can't be empty");
                    } else if (!secret.startsWith("SEC")) {
                        throw new IllegalArgumentException("Illegal secret:" + secret + ", it should start with SEC");
                    }
                    break;
                case IP:
                    break;
                default:
                    throw new IllegalArgumentException("Illegal securityType:" + securityType);
            }
        }

        String defaultMessageType = dingTalkRobotProperties.getMessageType();
        if (StringUtils.isEmpty(defaultMessageType)) {
            throw new NullPointerException("messageType can't be empty");
        } else if (!DingTalkMessageTypeEnum.check(defaultMessageType)) {
            throw new IllegalArgumentException("Illegal messageType:" + defaultMessageType);
        }
        checkSuccessful = true;
    }
}
